/***************************************************************************\
 * The Mattise Kernel														*
 * Copyright 2007 Matthew Iselin											*
 * Licensed under the GPL													*
 *																			*
 * reloc_elf.h																*
 *																			*
 * Relocates an ELF executable												*
 *																			*
\***************************************************************************/

// Pragmas
#pragma once

// Includes
#include <system.h>
#include <stdio.h>
#include <reloc.h>

// Constants

// ident section size
#define EI_NIDENT	16

// elf identification signature, offsets
#define EI_MAG0		0 // File identification
#define EI_MAG1		1 // File identification
#define EI_MAG2		2 // File identification
#define EI_MAG3		3 // File identification
#define EI_CLASS	4 // File class
#define EI_DATA		5 // Data encoding
#define EI_VERSION	6 // File version
#define EI_PAD		7 // Start of padding bytes
#define EI_NIDENT	16 // Size of e_ident[]

// elf identification signature, magic number
#define ELFMAG0		0x7f // offset EI_MAG0
#define ELFMAG1		'E' // offset EI_MAG1
#define ELFMAG2		'L' // offset EI_MAG2
#define ELFMAG3		'F' // offset EI_MAG3

// elf identification signature, architecture
#define ELFCLASSNONE	0 // Invalid class
#define ELFCLASS32		1 // 32-bit objects
#define ELFCLASS64		2 // 64-bit objects

// elf identification signature, byte order
#define ELFDATANONE	0 // invalid data encoding
#define ELFDATA2LSB	1 // most significant byte last
#define ELFDATA2MSB	2 // most significant byte first

// file types
#define ET_NONE		0 // no file type
#define ET_REL		1 // relocatable file
#define ET_EXEC		2 // executable file
#define ET_DYN		3 // shared object file
#define ET_CORE		4 // core file
#define ET_LOPROC	0xFF00 // processor-specific
#define ET_HIPROC	0xFFFF // processor-specific

// machine types
#define EM_NONE		0 // No machine
#define EM_M32		1 // AT&T WE 32100
#define EM_SPARC	2 // SPARC
#define EM_386		3 // Intel 80386
#define EM_68K		4 // Motorola 68000
#define EM_88K		5 // Motorola 88000
#define EM_860		7 // Intel 80860
#define EM_MIPS		8 // MIPS RS3000

// version types
#define EV_NONE		0 // Invalid version
#define EV_CURRENT	1 // Current version

// special section indexes
#define SHN_UNDEF		0
#define SHN_LORESERVE	0xff00
#define SHN_LOPROC		0xff00
#define SHN_HIPROC		0xff1f
#define SHN_ABS			0xfff1
#define SHN_COMMON		0xfff2
#define SHN_HIRESERVE	0xffff

// section types
#define SHT_NULL		0
#define SHT_PROGBITS	1
#define SHT_SYMTAB		2
#define SHT_STRTAB		3
#define SHT_RELA		4
#define SHT_HASH		5
#define SHT_DYNAMIC		6
#define SHT_NOTE		7
#define SHT_NOBITS		8
#define SHT_REL			9
#define SHT_SHLIB		10
#define SHT_DYNSYM		11
#define SHT_LOPROC		0x70000000
#define SHT_HIPROC		0x7fffffff
#define SHT_LOUSER		0x80000000
#define SHT_HIUSER		0xffffffff

// segment types
#define PT_NULL			0
#define PT_LOAD			1
#define PT_DYNAMIC		2
#define PT_INTERP		3
#define PT_NOTE			4
#define PT_SHLIB		5
#define PT_PHDR			6
#define PT_LOPROC		0x70000000
#define PT_HIPROC		0x7fffffff

// section attribute flags
#define SHF_WRITE		0x1
#define SHF_ALLOC		0x2
#define SHF_EXECINSTR	0x4
#define SHF_MASKPROC	0xf0000000

// symbol bindings
#define STB_LOCAL		0
#define STB_GLOBAL		1
#define STB_WEAK		2
#define STB_LOPROC		13
#define STB_HIPROC		15

// symbol types
#define STT_NOTYPE		0
#define STT_OBJECT		1
#define STT_FUNC		2
#define STT_SECTION		3
#define STT_FILE		4
#define STT_LOPROC		13
#define STT_HIPROC		15

// relocation "r_info" member macros
#define ELF32_R_SYM(i) ((i)>>8)
#define ELF32_R_TYPE(i) ((unsigned char)(i))
#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t))

// Types
typedef int Elf32_Sword;
typedef unsigned int Elf32_Word;
typedef unsigned int Elf32_Addr;
typedef unsigned int Elf32_Off;
typedef unsigned short Elf32_Half;

// file header
typedef struct {
	unsigned char	e_ident[EI_NIDENT];
	Elf32_Half		e_type;
	Elf32_Half		e_machine;
	Elf32_Word		e_version;
	Elf32_Addr		e_entry;
	Elf32_Off		e_phoff;
	Elf32_Off		e_shoff;
	Elf32_Word		e_flags;
	Elf32_Half		e_ehsize;
	Elf32_Half		e_phentsize;
	Elf32_Half		e_phnum;
	Elf32_Half		e_shentsize;
	Elf32_Half		e_shnum;
	Elf32_Half		e_shstrndx;
} Elf32_Ehdr;

// section header
typedef struct {
	Elf32_Word		sh_name;
	Elf32_Word		sh_type;
	Elf32_Word		sh_flags;
	Elf32_Addr		sh_addr;
	Elf32_Off		sh_offset;
	Elf32_Word		sh_size;
	Elf32_Word		sh_link;
	Elf32_Word		sh_info;
	Elf32_Word		sh_addralign;
	Elf32_Word		sh_entsize;
} Elf32_Shdr;

// program header
typedef struct {
	Elf32_Word		p_type;
	Elf32_Off		p_offset;
	Elf32_Addr		p_vaddr;
	Elf32_Addr		p_paddr;
	Elf32_Word		p_filesz;
	Elf32_Word		p_memsz;
	Elf32_Word		p_flags;
	Elf32_Word		p_align;
} Elf32_Phdr;

// symbol table entry
typedef struct {
	Elf32_Word		st_name;
	Elf32_Addr		st_value;
	Elf32_Word		st_size;
	unsigned char	st_info;
	unsigned char	st_other;
	Elf32_Half	st_shndx;
} Elf32_Sym;

// relocation information
typedef struct {
	Elf32_Addr		r_offset;
	Elf32_Word		r_info;
} Elf32_Rel;

typedef struct {
	Elf32_Addr		r_offset;
	Elf32_Word		r_info;
	Elf32_Sword		r_addend;
} Elf32_Rela;

// Class Definition

class ELFRelocation : public Relocation {
		
	public:
	
		// finds offsets
		int FindOffset( Elf32_Shdr* __sects, int cnt, int type, int notval = 0 );
		int FindOffset( Elf32_Shdr* __sects, int cnt, const char* secname, Elf32_Ehdr* myHead );
	
		// relocates the executable
		bool RelocateExecutable();
		
};
